import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { Errors } from '../types/errors';
import { UserRole, AuthUser } from '../types/auth';
import { log } from '../utils/logger';

// === Types ===
export interface AuthenticatedRequest extends Request {
  user: AuthUser;
}

// === Configuration ===
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';

// === Helper Functions ===
function extractToken(req: Request): string | null {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return null;
  }
  return authHeader.split(' ')[1];
}

function verifyToken(token: string): AuthUser {
  try {
    const decoded = jwt.verify(token, JWT_SECRET) as AuthUser;
    return decoded;
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      throw Errors.unauthorized('Token已过期');
    }
    throw Errors.unauthorized('无效的Token');
  }
}

// === Middleware ===
export function auth(req: Request, _res: Response, next: NextFunction): void {
  try {
    const token = extractToken(req);
    if (!token) {
      throw Errors.unauthorized('未提供Token');
    }

    const user = verifyToken(token);
    (req as AuthenticatedRequest).user = user;

    log.debug('用户认证成功', {
      userId: user._id,
      role: user.role
    });

    next();
  } catch (error) {
    next(error);
  }
}

export function roleAuth(allowedRoles: UserRole[]) {
  return (req: Request, _res: Response, next: NextFunction): void => {
    try {
      const user = (req as AuthenticatedRequest).user;
      
      if (!user) {
        throw Errors.unauthorized('需要认证');
      }

      if (!allowedRoles.includes(user.role)) {
        throw Errors.forbidden('无权访问此资源');
      }

      log.debug('角色验证成功', {
        userId: user._id,
        role: user.role,
        allowedRoles
      });

      next();
    } catch (error) {
      next(error);
    }
  };
}

// === Permission Checkers ===
export function canAccessResource(userId: string, resourceOwnerId: string, userRole?: UserRole): boolean {
  // Admins can access any resource
  if (userRole === 'admin') {
    return true;
  }
  
  // Users can only access their own resources
  return userId === resourceOwnerId;
}

export function hasRole(user: AuthUser, requiredRoles: UserRole[]): boolean {
  return requiredRoles.includes(user.role);
}
